using System;
using System.Collections.Generic;
using System.Diagnostics;
using EnvDTE;
using EnvDTE80;

namespace Microsoft.WowAddonStudio.Lua.RuntimeService.WowBench.Resolvers
{
	/// <summary>
	/// Resolves tokens in commands.
	/// </summary>
	public sealed class CommandResolver : ICommandResolver
	{
		private delegate string TokenResolverCallback();

		public static readonly string AddOnNameToken = "$AddOnName";
		public static readonly string SolutionNameToken = "$SolutionName";
		public static readonly string ActiveConfigNameToken = "$ActiveConfig";

		private readonly IDictionary<string, TokenResolverCallback> resolvers;
		private readonly DTE2 dte;

		#region Lifecycle Methods

		/// <summary>
		/// Initializes a new instance of the <see cref="CommandResolver"/> class.
		/// </summary>
		/// <param name="provider">The <see cref="IServiceProvider"/>.</param>
		public CommandResolver(IServiceProvider provider)
		{
			if (provider == null)
				throw new ArgumentNullException("provider");

			dte = (DTE2)provider.GetService(typeof(DTE));

			//Initialize resolver association
			resolvers = new Dictionary<string, TokenResolverCallback>
			            	{
			            		{AddOnNameToken, GetAddOnName},
			            		{SolutionNameToken, GetSolutionName},
			            		{ActiveConfigNameToken, GetActiveConfigName}
			            	};
		}

		#endregion

		#region ICommandResolver Members

		/// <summary>
		/// Resolve parameter tokens in the specified command.
		/// </summary>
		/// <param name="command"></param>
		/// <returns></returns>
		public string Resolve(string command)
		{
			if (!string.IsNullOrEmpty(command))
			{
				foreach (var resolver in resolvers)
				{
					if (command.Contains(resolver.Key))
					{
						string value = resolver.Value.Invoke();
						command = command.Replace(AddOnNameToken, value);
					}
				}
			}
			return command;
		}

		/// <summary>
		/// Resets the current state of <see cref="ICommandResolver"/>
		/// </summary>
		public void Reset()
		{
			return;
		}

		#endregion

		#region Private Functions

		/// <summary>
		/// Gets the name of the active AddOn.
		/// </summary>
		/// <returns></returns>
		private string GetAddOnName()
		{
			string addOnName = String.Empty;

			try
			{
				//Get active projects of active solution
				object activeSolutionProjects = dte.ActiveSolutionProjects;
				if (dte.Solution != null && activeSolutionProjects != null)
				{
					object[] objects = (object[]) activeSolutionProjects;
					//Convert all project objects to Project class
					Project[] projects = Array.ConvertAll(
						objects, project => (Project) project);
					//Get the title of the active project
					if (projects.Length > 0)
						addOnName = (string)projects[0].Properties.Item("AddonTitle").Value;
				}
			}
			catch (Exception e)
			{
				Trace.WriteLine(e);
			}

			return addOnName;
		}

		/// <summary>
		/// Gets the name of the active AddOn.
		/// </summary>
		/// <returns>The AddOn name.</returns>
		private string GetSolutionName()
		{
			string solutionName = String.Empty;

			try
			{
				if (dte.Solution != null)
					solutionName = (string) dte.Solution.Properties.Item("Name").Value;
			}
			catch (Exception e)
			{
				Trace.WriteLine(e);
			}

			return solutionName;
		}

		/// <summary>
		/// Gets the name of the active configuration.
		/// </summary>
		/// <returns>The active configuration name.</returns>
		private string GetActiveConfigName()
		{
			string solutionName = String.Empty;

			try
			{
				if (dte.Solution != null)
					solutionName = (string)dte.Solution.Properties.Item("ActiveConfig").Value;
			}
			catch (Exception e)
			{
				Trace.WriteLine(e);
			}
			return solutionName;
		}

		#endregion

	}
}